package com.songlanyun.modules.offlineorder.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.songlanyun.common.enums.IntegralConstant;
import com.songlanyun.common.enums.OfflineOrderConstant;
import com.songlanyun.common.enums.UserBillConstant;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.common.utils.*;
import com.songlanyun.common.utils.custom.MathUtils;
import com.songlanyun.modules.account.entity.AccountEntity;
import com.songlanyun.modules.account.entity.UserIdentityAssetEntity;
import com.songlanyun.modules.account.entity.UserInfoEntity;
import com.songlanyun.modules.account.model.vo.AccountInfoVO;
import com.songlanyun.modules.account.service.AccountService;
import com.songlanyun.modules.account.service.UserIdentityAssetService;
import com.songlanyun.modules.account.service.UserInfoService;
import com.songlanyun.modules.account.service.UserVerifiedService;
import com.songlanyun.modules.applyareaagent.service.ApplyAreaAgentService;
import com.songlanyun.modules.config.entity.ProfitSharingEntity;
import com.songlanyun.modules.config.service.ProfitSharingService;
import com.songlanyun.modules.integralrecord.entity.IntegralRecord;
import com.songlanyun.modules.integralrecord.service.IntegralRecordService;
import com.songlanyun.modules.offlineorder.dto.OfflineOrderBuildDto;
import com.songlanyun.modules.offlineorder.dto.OfflineOrderBuildVo;
import com.songlanyun.modules.offlineorder.dto.OfflineOrderCountVo;
import com.songlanyun.modules.offlineorderincome.service.OfflineOrderIncomeService;
import com.songlanyun.modules.pointconfig.entity.PointConfig;
import com.songlanyun.modules.pointconfig.service.PointConfigService;
import com.songlanyun.modules.shop.entity.ShopEntity;
import com.songlanyun.modules.shop.model.vo.ShopSlimVO;
import com.songlanyun.modules.shop.service.ShopService;
import com.songlanyun.modules.usergains.service.UserBillService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.songlanyun.modules.offlineorder.dao.OfflineOrderDao;
import com.songlanyun.modules.offlineorder.entity.OfflineOrder;
import com.songlanyun.modules.offlineorder.service.OfflineOrderService;
import org.springframework.transaction.annotation.Transactional;


@Service("offlineOrderService")
public class OfflineOrderServiceImpl extends ServiceImpl<OfflineOrderDao, OfflineOrder> implements OfflineOrderService {

    @Autowired
    private AccountService accountService;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private UserIdentityAssetService userIdentityAssetService;


    @Autowired
    private ProfitSharingService profitSharingService;

    @Autowired
    private ShopService shopService;

    @Autowired
    private PointConfigService pointConfigService;


    @Autowired
    private UserBillService userBillService;

    @Autowired
    private IntegralRecordService integralRecordService;


    @Autowired
    private ApplyAreaAgentService applyAreaAgentService;

    @Autowired
    private OfflineOrderIncomeService offlineOrderIncomeService;

    @Autowired
    private OfflineOrderDao offlineOrderDao;


    @Override
    public OfflineOrder create(OfflineOrder entity) {
        this.baseMapper.insert(entity);
        return entity;
    }

    @Override
    public OfflineOrder modify(OfflineOrder entity) {
        this.baseMapper.updateById(entity);
        return entity;
    }

    @Override
    public void remove(Long id) {

    }

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        String date = MapUtil.getStr(params, "date");
        Date startTime = null;
        Date endTime = null;
        if(StringUtils.isNotEmpty(date))
        {
            Date d = DateUtils.stringToDate(date,"yyyy-MM-dd");
            startTime = DateUtil.beginOfDay(d);
            endTime = DateUtil.endOfDay(d);
        }
        Long shopId = MapUtil.getLong(params, "shop_id");
        Long areaAgentId = MapUtil.getLong(params, "area_agent_id");
        String mobile = MapUtil.getStr(params, "mobile");
        List<Long> shopIds = new ArrayList<>();
        if(ObjectUtil.isNotNull(areaAgentId) && areaAgentId>0 )
        {
            List<ShopSlimVO> shopSlimVOS = applyAreaAgentService.myOfflineShops(areaAgentId);
            shopIds = shopSlimVOS.stream().map(ShopSlimVO::getId).collect(Collectors.toList());
            shopIds.add(0L);
        }

        Long userId = MapUtil.getLong(params, "user_id");
        Integer comment = MapUtil.getInt(params, "comment");
        LambdaQueryWrapper<OfflineOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(ObjectUtil.isNotNull(startTime),OfflineOrder::getCreateTime,startTime);
        wrapper.le(ObjectUtil.isNotNull(endTime),OfflineOrder::getCreateTime,endTime);
        wrapper.like(StringUtils.isNotBlank(mobile),OfflineOrder::getUserMobile,mobile);
        wrapper.eq(ObjectUtil.isNotNull(shopId)&& shopId>=0,OfflineOrder::getShopId,shopId);
        wrapper.eq(ObjectUtil.isNotNull(userId)&& userId>=0,OfflineOrder::getUserId,userId);
        wrapper.eq(ObjectUtil.isNotNull(comment) && comment>=0,OfflineOrder::getComment,comment);
        wrapper.in(CollectionUtil.isNotEmpty(shopIds),OfflineOrder::getShopId,shopIds);
        wrapper.orderByDesc(OfflineOrder::getCreateTime);

        IPage<OfflineOrder> page = this.page(
                new Query<OfflineOrder>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

    @Override
    public OfflineOrderCountVo dateCount(Map<String, Object> params) {
        Date startTime = null;
        Date endTime = null;
        String date = MapUtil.getStr(params, "date");
        if(StringUtils.isNotEmpty(date))
        {
            Date d = DateUtils.stringToDate(date,"yyyy-MM-dd");
            startTime = DateUtil.beginOfDay(d);
            endTime = DateUtil.endOfDay(d);
            params.put("start_time",startTime);
            params.put("end_time",endTime);
        }
        OfflineOrderCountVo vo = this.baseMapper.dateCount(params);
        return vo;
    }

    @Override
    public BigDecimal selectCountShopConsumeIntegralAble() {
        return offlineOrderDao.selectCountShopConsumeIntegralAble();
    }


    @Override
    public OfflineOrderBuildVo build(OfflineOrderBuildDto dto) {
        OfflineOrderBuildVo vo = new OfflineOrderBuildVo();
        AccountEntity user = accountService.getUserById(dto.getUserId(), true);
        vo.setUserId(user.getId());
        vo.setUserMobile(user.getMobile());
        UserInfoEntity userInfoEntity = userInfoService.loadById(dto.getUserId(), true);
        vo.setUserName(StringUtils.isNotEmpty(userInfoEntity.getRealName())?userInfoEntity.getRealName():userInfoEntity.getNickname());
        vo.setSalesMoney(dto.getSalesMoney());
        vo.setDiscountRatio(dto.getDiscountRatio());
        vo.setDiscountMoney(MathUtils.setScale(dto.getSalesMoney().doubleValue()*dto.getDiscountRatio().doubleValue()/100));
        ProfitSharingEntity info = profitSharingService.info();
        vo.setGiveUserCommissionAble((MathUtils.setScale(vo.getDiscountMoney().doubleValue()*info.getOfflineOrderConsumerContribute().doubleValue())));
        vo.setGiveShopCommissionAble((MathUtils.setScale(vo.getDiscountMoney().doubleValue()*info.getOfflineOrderShopContribute().doubleValue())));
        ShopEntity shopEntity = shopService.loadShopBy(dto.getShopId(), true);
        vo.setShopId(dto.getShopId());
        vo.setShopName(shopEntity.getShopName());
        UserIdentityAssetEntity userIdentityAssetEntity = userIdentityAssetService.loadByIdForLock(shopEntity.getUserId(), true);
        vo.setCurrentIntegralAble(userIdentityAssetEntity.getIntegralAble());
        PointConfig config = pointConfigService.loadConfig(true);
        vo.setShopConsumeIntegralAble(MathUtils.setScaleDown(vo.getDiscountMoney().doubleValue()/config.getPointPrice().doubleValue(),8));
        vo.setEnoughShopConsume(vo.getCurrentIntegralAble().compareTo(vo.getShopConsumeIntegralAble())>=0);
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OfflineOrder createOrder(OfflineOrderBuildDto dto) {
        OfflineOrderBuildVo vo = this.build(dto);
        if(!vo.getEnoughShopConsume())
        {
            throw new RRException("您的积分不够,不能上报订单");
        }
        OfflineOrder offlineOrder = new OfflineOrder();
        offlineOrder.setOrderCode(OrderGen.generateOrderNo());
        offlineOrder.setUserId(vo.getUserId());
        offlineOrder.setUserMobile(vo.getUserMobile());
        offlineOrder.setUserName(vo.getUserName());
        offlineOrder.setSalesMoney(vo.getSalesMoney());
        offlineOrder.setDiscountRatio(vo.getDiscountRatio());
        offlineOrder.setDiscountMoney(vo.getDiscountMoney());
        offlineOrder.setCurrentIntegralAble(vo.getCurrentIntegralAble());
        offlineOrder.setGiveUserCommissionAble(vo.getGiveUserCommissionAble());
        offlineOrder.setGiveShopCommissionAble(vo.getGiveShopCommissionAble());
        offlineOrder.setShopConsumeIntegralAble(vo.getShopConsumeIntegralAble());
        offlineOrder.setShopId(vo.getShopId());
        offlineOrder.setShopName(vo.getShopName());
        offlineOrder.setCreateTime(new Date());
        offlineOrder.setPayMode(OfflineOrderConstant.PayMode.getByCode(dto.getPayMode()));
        offlineOrder.setRemark(dto.getRemark());
        this.create(offlineOrder);

        //给用户贡献值
        userBillService.inBill(offlineOrder.getUserId(),
                String.format("商家上报了您的订单%s,您消费了%s元", offlineOrder.getOrderCode(),offlineOrder.getSalesMoney().toString()),
                UserBillConstant.InnerMode.BUY_INCOME,
                offlineOrder.getGiveUserCommissionAble(),
                offlineOrder.getOrderCode(),"系统");

        ShopEntity shopEntity = shopService.loadShopBy(vo.getShopId(), true);

        //给商家贡献值
        userBillService.inBill(shopEntity.getUserId(),
                String.format("您上报了订单%s", offlineOrder.getOrderCode()),
                UserBillConstant.InnerMode.BUY_INCOME,
                offlineOrder.getGiveShopCommissionAble(),
                offlineOrder.getOrderCode(),"系统");

        //上报订单消耗积分
        integralRecordService.outer(shopEntity.getUserId(), vo.getShopConsumeIntegralAble(), IntegralConstant.OuterMode.OFFLINE_CONSUMPTION_POINT,
                IntegralConstant.IntegralModelType.OFFLINE_CONSUMPTION_POINT, offlineOrder.getId(), "上报订单消耗积分");

        //分润
        offlineOrderIncomeService.income(offlineOrder);
        return offlineOrder;
    }



}
